package com.jasmine.bjstkserver.manager.os;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.jasmine.bjstkserver.core.config.exception.BjsException;
import com.jasmine.core.constants.enums.DictEnum;
import com.jasmine.bjstkserver.server.dict.DictService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author jasmineXz
 */
@Component
public class AliOssManager extends AbstractOsManager implements OsManager {
    private static final Logger log = LoggerFactory.getLogger(AliOssManager.class);
    private static final String ENDPOINT         = "ENDPOINT";
    private static final String ACCESSKEY_ID     = "ACCESSKEY_ID";
    private static final String ACCESSKEY_SECRET = "ACCESSKEY_SECRET";
    private static final String BUCKET_NAME      = "BUCKET_NAME";
    private static final String FILE_PATH        = "FILE_PATH";
    private static final String DOMAIN           = "DOMAIN";

    @Autowired
    private DictService dictService;


    /**
     * 上传文件流
     * @param inputStream 输入流
     * @param fileName 文件名
     */
    @Override
    public String put(InputStream inputStream,String fileName) {
        log.info("[BJSTK] ali os upload, {}",fileName);
        Map<String,String> param = getParam();
        OSS ossClient = initOssInstance(param);
        String name;
        try {
            name = param.get(FILE_PATH) + (StrUtil.isBlank(fileName) ? UUID.randomUUID().toString() + ".jpg" : fileName);
            ossClient.putObject(param.get(BUCKET_NAME), name,
                    inputStream,
                    initObjectMetadata(fileName)).getETag();
        } finally {
            ossClient.shutdown();
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return param.get(DOMAIN) + name;
    }


    /**
     * 非HTTP请求线程上传文件
     * @param inputStream 文件流
     * @param fileName 文件名
     * @param userId 用户ID,用于获取该用户字典
     * @return 文件地址
     */
    @Override
    public String putAsync(InputStream inputStream, String fileName, Integer userId) {
        Map<String,String> param = getParam(userId);
        OSS ossClient = initOssInstance(param);
        String name;
        try {
            name = StrUtil.isBlank(fileName) ? UUID.randomUUID().toString() + ".jpg" : fileName;
            ObjectMetadata objectMetadata = initObjectMetadata(fileName);
            ossClient.putObject(param.get(BUCKET_NAME), param.get(FILE_PATH) + name,
                    inputStream,
                    objectMetadata);
        } finally {
            ossClient.shutdown();
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return param.get(DOMAIN) + name;
    }


//    /**
//     * 上传文件
//     * @param file 文件
//     */
//    @Override
//    public String put(File file,String fileName) {
//        Map<String,String> param = getParam();
//        OSS ossClient = initOssInstance(param);
//        PutObjectRequest putObjectRequest = new PutObjectRequest(
//                param.get(BUCKET_NAME), param.get(FILE_PATH) + file.getName(), file);
//        ossClient.putObject(putObjectRequest);
//        return null;
//    }


    /**
     * 上传文件
     * @param file 文件
     */
    @Override
    public String put(MultipartFile file,String fileName) {
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return put(inputStream,fileName);
    }


//    /**
//     * 上传字符串
//     * @param file base64
//     */
//    @Override
//    public String put(String file,String fileName) {
//        BufferedImage image = ImgUtil.toImage(file);
//        ByteArrayOutputStream os = new ByteArrayOutputStream();
//        try {
//        ImageOutputStream imOut = ImageIO.createImageOutputStream(os);
//            ImageIO.write(image, "jpg", imOut);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        InputStream input = new ByteArrayInputStream(os.toByteArray());
//        return put(input,null);
//    }


    /**
     * 删除文件
     * @param fileName 文件名称
     */
    @Async
    @Override
    public void deleteAsync(String fileName,Integer userId) {
        Map<String,String> param = getParam(userId);
        OSS ossClient = initOssInstance(param);
        String objName = StrUtil.removeAll(fileName,param.get(DOMAIN));
        try {
            ossClient.deleteObject(param.get(BUCKET_NAME),objName);
        } finally {
            ossClient.shutdown();
        }
        log.info("[BJSTK] 删除OSS文件 : {}",fileName);
    }


    /**
     * 列举存储空间
     */
    public List<Bucket> getBuckets () {
        Map<String,String> param = getParam();
        OSS ossClient = initOssInstance(param);
        List<Bucket> buckets = ossClient.listBuckets();
        if (CollectionUtil.isEmpty(buckets)) {
            throw new BjsException("为查询到bucket");
        }
        ossClient.shutdown();
        return buckets;
    }


    /**
     * 存储空间地域信息
     * @param bucketName bucket名称
     * @return 地域信息
     */
    public String getBucketLocation (String bucketName) {
        Map<String,String> param = getParam();
        OSS ossClient = initOssInstance(param);
        String location = ossClient.getBucketLocation(bucketName);
        ossClient.shutdown();
        return location;
    }


    /**
     * 获取文件列表
     * @param bucketName bucket名称
     * @param prefix 文件路径
     */
    public List<OSSObjectSummary> getFiles (String bucketName, String prefix) {
        Map<String,String> param = getParam();
        OSS ossClient = initOssInstance(param);
        ListObjectsRequest request =
                new ListObjectsRequest(bucketName)
                        .withPrefix(prefix)
                        .withMaxKeys(50);

        ObjectListing listing = ossClient.listObjects(request);
        List<OSSObjectSummary> sums = listing.getObjectSummaries();
        ossClient.shutdown();
        return sums;
    }


    /**
     * 获取文件夹
     * @param bucketName bucket名称
     * @param prefix 文件路径
     */
    public List<String> getFolders (String bucketName, String prefix) {
        Map<String,String> param = getParam();
        OSS ossClient = initOssInstance(param);
        ListObjectsRequest request =
                new ListObjectsRequest(bucketName)
                        .withPrefix(prefix)
                        .withMaxKeys(50)
                        .withDelimiter("/");
        ObjectListing listing = ossClient.listObjects(request);
        ossClient.shutdown();
        return listing.getCommonPrefixes();

    }


    private OSS initOssInstance (Map<String,String> param){
        return new OSSClientBuilder().build(
                param.get(ENDPOINT),
                param.get(ACCESSKEY_ID),
                param.get(ACCESSKEY_SECRET));
    }


    private ObjectMetadata initObjectMetadata(String fileName) {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType(matchContentType(fileName));
        return objectMetadata;
    }


    private Map<String,String> getParam(){
        return dictService.getDict(DictEnum.ALIYUNOSS.code());
    }


    private Map<String,String> getParam(Integer userId){
        return dictService.getDict(DictEnum.ALIYUNOSS.code(),userId);
    }

}
